import json
from dataclasses import is_dataclass, asdict, dataclass
from ..base import *
from functools import wraps
import inspect

class Serializable:
    """可序列化基类，提供类型标记支持"""
    __serialize_type__ = True
    
    def __serialize__(self) -> Dict[str, Any]:
        """默认序列化方法"""
        if is_dataclass(self):
            return asdict(self)
        return self.__dict__.copy()
    
    @classmethod
    def __deserialize__(cls, data: Dict[str, Any]) -> Any:
        """默认反序列化方法"""
        return cls(**data)

def serializable(cls: Type) -> Type:
    """使类可序列化的装饰器"""
    if not hasattr(cls, '__serialize_type__'):
        cls.__serialize_type__ = True
    
    if not hasattr(cls, '__serialize__'):
        cls.__serialize__ = Serializable.__serialize__
    
    if not hasattr(cls, '__deserialize__'):
        cls.__deserialize__ = Serializable.__deserialize__
    
    return cls

def custom_serializer(method: Callable) -> Callable:
    """
    装饰成员方法作为自定义序列化器
    
    被装饰的方法应返回一个字典，将被用作序列化结果
    """
    @wraps(method)
    def wrapper(self) -> Dict[str, Any]:
        result = method(self)
        if not isinstance(result, dict):
            raise ValueError("Custom serializer must return a dictionary")
        return result
    
    # 标记这个方法为自定义序列化器
    wrapper._is_custom_serializer = True
    return wrapper

def custom_deserializer(method: Callable) -> Callable:
    """
    装饰类方法作为自定义反序列化器
    
    被装饰的方法应接受一个字典参数并返回类的实例
    """
    @wraps(method)
    def wrapper(cls, data: Dict[str, Any]) -> Any:
        return method(cls, data)
    
    # 标记这个方法为自定义反序列化器
    wrapper._is_custom_deserializer = True
    return wrapper

class JsonEncoder(json.JSONEncoder):
    """支持类型标记的JSON编码器"""
    
    def default(self, obj: Any) -> Any:
        if hasattr(obj, '__serialize_type__'):
            # 查找自定义序列化方法
            for name, method in inspect.getmembers(obj.__class__, predicate=inspect.isfunction):
                if hasattr(method, '_is_custom_serializer'):
                    result = method(obj)
                    result['__type__'] = obj.__class__.__name__
                    return result
            
            # 使用默认序列化
            result = obj.__serialize__()
            result['__type__'] = obj.__class__.__name__
            return result
        return super().default(obj)

def json_decode_hook(dct: Dict[str, Any], namespace: Optional[Dict[str, Type]] = None) -> Any:
    """JSON解码钩子，处理类型标记"""
    if '__type__' in dct:
        class_name = dct.pop('__type__')
        target_class = None
        
        # 从命名空间查找类
        if namespace and class_name in namespace:
            target_class = namespace[class_name]
        else:
            # 全局查找
            target_class = globals().get(class_name)
        
        if target_class:
            # 查找自定义反序列化方法
            for name, method in inspect.getmembers(target_class, predicate=inspect.ismethod):
                if hasattr(method, '_is_custom_deserializer'):
                    return method(dct)
            
            # 使用默认反序列化
            if hasattr(target_class, '__deserialize__'):
                return target_class.__deserialize__(dct)
    
    return dct

def dumps(obj: Any, **kwargs) -> str:
    """序列化对象为JSON字符串"""
    return json.dumps(obj, cls=JsonEncoder, **kwargs)

def loads(json_str: str, namespace: Optional[Dict[str, Type]] = None, **kwargs) -> Any:
    """从JSON字符串反序列化对象"""
    return json.loads(
        json_str, 
        object_hook=lambda dct: json_decode_hook(dct, namespace), 
        **kwargs
    )

# 示例使用
if __name__ == '__main__':
    @serializable
    @dataclass
    class Point:
        x: int
        y: int
        
        def __repr__(self):
            return f"Point({self.x}, {self.y})"

    @serializable
    class Person:
        def __init__(self, name: str, age: int):
            self.name = name
            self.age = age
        
        @custom_serializer
        def serialize(self) -> Dict[str, Any]:
            return {'value': f"{self.name}:{self.age}"}
        
        @classmethod
        @custom_deserializer
        def deserialize(cls, data: Dict[str, Any]) -> 'Person':
            name, age = data['value'].split(':')
            return cls(name, int(age))
        
        def __repr__(self):
            return f"Person(name={self.name}, age={self.age})"

    # 测试序列化
    p = Point(10, 20)
    person = Person("Alice", 30)
    
    # 序列化
    serialized = dumps([p, person])
    print("Serialized:", serialized)
    
    # 反序列化
    deserialized = loads(serialized, {'Point': Point, 'Person': Person})
    print("Deserialized:", deserialized)
    print("Type check Point:", isinstance(deserialized[0], Point))
    print("Type check Person:", isinstance(deserialized[1], Person))